#pragma once

#include "functor.hpp"
#include "allocator.hpp"
#include "list_node.hpp"
#include "log_functor.hpp"
#include "reverse_iterator.hpp"

namespace zuck
{
	template<typename _ListType>
	class _ListConstIterator {
	private:
		using _Self = _ListConstIterator<_ListType>;
	public:
		using value_type	    = typename _ListType::value_type;
		using pointer		    = const value_type*;
		using reference			= const value_type&;
		using difference_type	= typename _ListType::difference_type;
		using iterator_category = zuck::bidirectional_iterator_tag;
	public:
		using _Node_ptr	= const __list_node<value_type>*;
	private:
		_Node_ptr _m_iter;
		_Node_ptr _m_prev;
	public:
		explicit _ListConstIterator(_Node_ptr iter, _Node_ptr prev)
			: _m_iter(iter), _m_prev(prev) {}

		_ListConstIterator(const _Self& other)
			: _m_iter(other._m_iter), _m_prev(other._m_prev) {}

		inline _ListConstIterator(_Self&& other)noexcept
			: _m_iter(other._m_iter), _m_prev(other._m_prev) 
		{
			other._m_iter = null;
			other._m_prev = null;
		}

		inline virtual ~_ListConstIterator()
        {
			_m_iter = null;
			_m_prev = null;
		}

		[[nodiscard]] inline _Node_ptr get_unwrapped()const noexcept
		{
			return _m_iter;
		}

		inline _ListConstIterator& operator=(const _Self& other)
		{
			_m_iter = other._m_iter;
			_m_prev = other._m_prev;
			return *this;
		}

		inline _ListConstIterator& operator=(_Self&& other)noexcept
		{
			_m_iter = other._m_iter;
			_m_prev = other._m_prev;
			other._m_iter = null;
			other._m_prev = null;
			return *this;
		}

		[[nodiscard]] inline pointer operator->()const noexcept
		{
			if constexpr (debug_) {
				if (!_m_iter->_m_data) {
					debug_log::derror(zuck::SEG_WrongIter, 
						"can not referenced nullptr");
				}
			}
			return _m_iter->_m_data;
		}

		[[nodiscard]] inline reference operator*()const noexcept
		{
			if constexpr (debug_) {
				if (!_m_iter->_m_data) {
					debug_log::derror(zuck::SEG_WrongIter, 
						"can not referenced nullptr");
				}
			}
			return *(_m_iter->_m_data);
		}

		inline _ListConstIterator& operator++()noexcept
		{
			auto* _Next = _m_iter->_m_n;
			if constexpr (debug_) {
				if (!_m_iter && !_Next) {
					debug_log::derror(SegmentCase::SEG_OutofRange,
						    "Segmentfault : end list iterator cannot be referenced !");
				}
			}
			_m_iter = _Next;
			return *this;
		}

		[[nodiscard]] inline _ListConstIterator operator++(int)noexcept
		{
			auto _Tmp = *this;
			++(*this);
			return _Tmp;
		}

		inline _ListConstIterator& operator--()noexcept
		{
			if constexpr (debug_) {
				if (_m_iter && !_m_prev) {
					debug_log::derror(SegmentCase::SEG_OutofRange,
						    "Segmentfault : nullptr cannot be referenced");
				}
			}
			_m_iter = !_m_iter ? _m_prev : _m_iter->_m_p;
			return *this;
		}

		[[nodiscard]] inline _ListConstIterator operator--(int)
		{
			auto _Tmp = *this;
			--(*this);
			return _Tmp;
		}

		[[nodiscard]] inline bool operator!=(const _Self& other)const noexcept
		{
			return static_cast<bool>(_m_iter != other._m_iter);
		};

		[[nodiscard]] inline bool operator==(const _Self& other)const noexcept
		{
			return static_cast<bool>(_m_iter != other._m_iter);
		}
	};

	template<typename _ListType>
	class _ListIterator : public _ListConstIterator<_ListType>
	{
	private:
		using _Base = _ListConstIterator<_ListType>;
		using _Self = _ListIterator<_ListType>;
	public:
		using value_type		= typename _Base::value_type;
		using pointer			= value_type*;
		using reference			= value_type&;
		using difference_type	= typename _Base::difference_type;
        using iterator_category = typename _Base::iterator_category;
	private:
		using _Node_ptr = __list_node<value_type>*;
	public:
		explicit _ListIterator(_Node_ptr iter = null, _Node_ptr prev = null)
			: _Base(iter, prev) {}

		_ListIterator(const _Self& other) : _Base(other) {}

		_ListIterator(_Self&& other)noexcept : _Base(zuck::move(other)) {}

		[[nodiscard]] inline reference operator*()noexcept
		{
			return const_cast<reference>(_Base::operator*());
		}

		[[nodiscard]] inline pointer operator->()noexcept
		{
			return const_cast<pointer>(_Base::operator->());
		}

		inline _Self& operator++()noexcept
		{
			_Base::operator++();
			return *this;
		}

		inline _Self operator++(int)noexcept
		{
			auto _Tmp = *this;
			_Base::operator++();
			return _Tmp;
		}

		inline _Self& operator--()noexcept
		{
			_Base::operator--();
			return *this;
		}

		inline _Self operator--(int)noexcept
		{
			auto _Tmp = *this;
			_Base::operator--();
			return _Tmp;
		}
	};

	template<typename _ListType>
	class _ListConstReverseIterator {
	public:
		using value_type = typename _ListType::value_type;
		using pointer = const value_type*;
		using reference = const value_type&;
		using iterator_category = zuck::bidirectional_iterator_tag;
	private:
		using _Node_ptr = const __list_node<value_type>*;
		using _Self = _ListConstReverseIterator<_ListType>;
	private:
		_Node_ptr _m_iter;
		_Node_ptr _m_prev;
	public:
		explicit _ListConstReverseIterator(_Node_ptr _Ptr, _Node_ptr _Prev)
			: _m_iter(null), _m_prev(null) {}

		inline virtual ~_ListConstReverseIterator()
		{
			_m_iter = null;
			_m_prev = null;
		}

		inline _ListConstReverseIterator(const _Self& other)
			: _m_iter(other._m_iter), _m_prev(other._m_prev) {}

		inline _ListConstReverseIterator(_Self&& other)noexcept
			: _m_iter(other._m_iter), _m_prev(other._m_prev)
		{
			other._m_iter = null;
			other._m_prev = null;
		}

		[[nodiscard]] inline pointer get_unwrapped()const noexcept
		{
			return _m_iter;
		}

		[[nodiscard]] inline pointer operator->()
		{
			if constexpr (debug_) {
				if (!_m_iter->_m_data) {
					debug_log::derror(zuck::SEG_WrongIter, "can not referenced nullptr");
				}
			}
			return _m_iter->_m_data;
		}

		[[nodiscard]] inline reference operator*()const noexcept
		{
			if constexpr (debug_) {
				if (!_m_iter->_m_data) {
					debug_log::derror(zuck::SEG_WrongIter, "can not referenced nullptr");
				}
			}
			return *(_m_iter->_m_data);
		}

		inline _ListConstReverseIterator& operator=(const _Self& other)
		{
			_m_iter = other._m_iter;
			_m_prev = other._m_prev;
			return *this;
		}

		inline _ListConstReverseIterator& operator=(_Self&& other)noexcept
		{
			_m_iter = other._m_iter;
			_m_prev = other._m_prev;
			other._m_iter = null;
			other._m_prev = null;
			return *this;
		}

		inline _ListConstReverseIterator& operator++()noexcept
		{
			const auto* _Next = _m_iter->_m_p;
			if constexpr (debug_) {
				if (!_m_iter && !_Next) {
					debug_log::derror(SegmentCase::SEG_OutofRange,
						"Segment fault : rend list iterator cannot be referenced");
				}
			}
			_m_iter = _Next;
			return *this;
		}

		[[nodiscard]] inline _ListConstReverseIterator operator++(int)noexcept
		{
			auto _Tmp = *this;
			++(*this);
			return _Tmp;
		}

		inline _ListConstReverseIterator& operator--()noexcept
		{
			if constexpr (debug_) {
				if (_m_iter && !_m_prev) {
					debug_log::derror(SegmentCase::SEG_OutofRange,
						"Segment fault: rend list iterator cannot be referenced");
				}
			}
			_m_iter = (_m_iter == null) ? _m_prev : (_m_iter = _m_iter->_m_n);
			return *this;
		}

		[[nodiscard]] inline _ListConstReverseIterator operator--(int)noexcept
		{
			auto _Tmp = *this;
			--(*this);
			return _Tmp;
		}

		[[nodiscard]] inline bool operator!=(const _Self& other)const noexcept
		{
			return static_cast<bool>(_m_iter != other._m_iter);
		}

		[[nodiscard]] inline bool operator==(const _Self& other)const noexcept
		{
			return static_cast<bool>(_m_iter == other._m_iter);
		}
	};

	template<typename _ListType>
	class _ListReverseIterator : public _ListConstReverseIterator<_ListType>
	{
	private:
		using _Base = _ListConstReverseIterator<_ListType>;
		using _Self = _ListReverseIterator<_ListType>;
	public:
		using value_type		= typename _Base::value_type;
		using pointer			= value_type*;
		using reference			= value_type&;
		using iterator_category = typename _Base::iterator_category;
	private:
		using _Node_ptr = __list_node<value_type>*;
	public:
		explicit _ListReverseIterator(_Node_ptr iter, _Node_ptr prev)
			: _Base(iter, prev) {}

		_ListReverseIterator(const _Self& other)
            : _Base(other) {}

        _ListReverseIterator(_Self&& other)noexcept
            : _Base(zuck::move(other)) {}

		inline _Self& operator=(const _Self& other)
		{
			_Base::operator=(other);
			return *this;
		}

		inline _Self& operator=(_Self&& other)noexcept
		{
			_Base::operator=(zuck::move(other));
			return *this;
		}

		[[nodiscard]] inline pointer operator->()const noexcept
		{
			return const_cast<pointer>(_Base::operator->());
		}

		[[nodiscard]] inline reference operator*()const noexcept
		{
			return const_cast<reference>(_Base::operator*());
		}

		inline _Self& operator++()noexcept
		{
			return _Base::operator++();
		}

		[[nodiscard]] inline _Self operator++(int)noexcept
		{
			auto _Tmp = *this;
			++(*this);
			return _Tmp;
		}

		inline _Self& operator--()noexcept
		{
			_Base::operator--();
			return *this;
		}

		[[nodiscard]] inline _Self operator--(int)noexcept
		{
			auto _Tmp = *this;
			--(*this);
			return _Tmp;
		}
	};


	template<typename T, typename Alloc = zuck::allocator<T>>
	class list {
		static_assert(
			!zuck::is_const_v<T> || !zuck::is_volatile_v<T>, 
			"template parameter can not be const or volatile");
	private:
		using _Self		  = zuck::list<T, Alloc>;
		using _Node_Alloc = zuck::__list_node<T>;
		using _Node_ptr   = zuck::__list_node<T>*;
		using _Alty_tts   = zuck::allocator_traits<Alloc>;
	public:
		using value_type	   = typename _Alty_tts::value_type;
		using pointer          = typename _Alty_tts::pointer;
		using const_pointer    = typename _Alty_tts::const_pointer;
		using reference		   = typename _Alty_tts::reference;
		using const_reference  = typename _Alty_tts::const_reference;
		using allocator_type   = typename _Alty_tts::allocator_type;
		using size_type		   = typename _Alty_tts::size_type;
		using difference_type  = typename _Alty_tts::difference_type;
	public:
		using iterator				 = _ListIterator<list<T, Alloc>>;
		using const_iterator		 = _ListConstIterator<list<T, Alloc>>;
		using reverse_iterator		 = _ListReverseIterator<list<T, Alloc>>;
		using const_reverse_iterator = _ListConstReverseIterator<list<T, Alloc>>;
	private:
		_Node_ptr _m_head;
		_Node_ptr _m_tail;
		size_type _m_cnt;
		Alloc     alloc;
	public:
		constexpr list()
			: _m_head(null), _m_tail(null)
			, _m_cnt(0), alloc(Alloc{}) {}

		inline explicit list(size_type const _Newsize, Alloc al)
			:_m_head(), _m_tail(), _m_cnt(0), alloc(al)
		{
			__construct_n(_Newsize, T{});
		}

		inline explicit list(size_type const _Size, T const Valty)
			:_m_head(null), _m_tail(null), _m_cnt(_Size), alloc(Alloc{})
		{
			__construct_n(_Size, Valty);
		}

		inline explicit list(size_type const _Size, T const Valty, Alloc al)
			:_m_head(null), _m_tail(null), _m_cnt(_Size), alloc(al)
        {
			__construct_n(_Size, Valty);
		}

		inline list(std::initializer_list<T> data)
			: _m_head(null), _m_tail(null), _m_cnt(0), alloc(Alloc{})
		{
			__construct_range(data.begin(), data.end());
		}

		inline explicit list(std::initializer_list<T> data, Alloc al)
			: _m_head(), _m_tail(), _m_cnt(0), alloc(al)
		{
			__construct_range(data.begin(), data.end());
		}

		template<typename PointerType, 
            zuck::enable_if_t<zuck::is_iterator_v<PointerType>, int> = 0>
		inline explicit list(PointerType _Bgn, PointerType _End)
			:_m_head(null), _m_tail(null), _m_cnt(0)
		{
			__construct_range(_Bgn, _End);
		}

		template<typename PointerType,
			zuck::enable_if_t<zuck::is_iterator_v<PointerType>, int> = 0>
		inline explicit list(PointerType _Bgn, PointerType _End, Alloc al)
			:_m_head(null), _m_tail(null), _m_cnt(0), alloc(al)
		{
			__construct_range(_Bgn, _End);
		}

		inline list(const _Self& other)
			:_m_head(null), _m_tail(null), _m_cnt(0)
		{
			assign(other.begin(), other.end());
		}

		inline list(_Self&& other)noexcept
			:_m_head(null), _m_tail(null), _m_cnt(0)
		{
			__move_construct(zuck::forward<list>(other));
		}

		inline ~list()
		{
			__destroy_list();
		}

		void assign(const size_type _NewSize, const T& val)
		{
			auto const _OldSize = size();
			auto _Begin			= begin();
			auto const _End		= end();
			__verify_size(_NewSize);
			if (_NewSize > _OldSize) {
				zuck::fill(_Begin, _End, val);
				for (int i = 0; i < _NewSize - _OldSize; ++i) {
					__emplace_back(val);
				}
				return;
			}
			__free_tail_n(_OldSize - _NewSize);
			zuck::fill(_Begin, end(), val);
		}

		inline void assign(std::initializer_list<T> data)
		{
			__assign_range(data.begin(), data.end());
		}

		template<typename Iterator,
			zuck::enable_if_t<zuck::is_iterator_v<Iterator>, int> = 0>
		inline void assign(Iterator _Bgn, Iterator _End)
		{
			__assign_range(_Bgn, _End);
		}

		inline void clear() { __destroy_data(); }

		template<typename...Args>
		inline iterator emplace(const_iterator wh, Args&&...args)
		{ 
			return __emplace_aux(wh, zuck::forward<Args>(args)...);
		}

		template<typename...Args>
		inline reference emplace_front(Args&&...args)
		{ 
			return *__emplace_front(zuck::forward<Args>(args)...);
		}

		template<typename...Args>
		inline reference emplace_back(Args&&...args)
		{ 
			return *__emplace_back(zuck::forward<Args>(args)...);
		}

		[[nodiscard]] inline bool erase(const T& val)noexcept
		{ 
			return __rm_node(val);
		}

		[[nodiscard]] inline bool erase(T&& val)noexcept
		{
			return __rm_node(val);
		}

		[[nodiscard]] inline iterator erase(const_iterator wh)
		{
			_Node_ptr _Ptr = wh.get_unwrapped();

			_Node_ptr _Res = _Ptr->_m_n;
			zuck::swap(_Ptr->_m_data, _Res->_m_data);
			_Res->_m_n->_m_p = _Ptr;
			_Ptr->_m_n = _Res->_m_n;
			alloc.deallocate(_Res->_m_data);
			_Node_Alloc::_Deallocate(_Res);
			--_m_cnt;
			return iterator(_Res->_m_n);
		}

		[[nodiscard]] inline reference front()noexcept
		{
			if constexpr (debug_) {
				if (empty()) {
					debug_log::derror(zuck::SEG_WrongIter,
						"Segmentfault: invalid address !");
				}
			}
			return *_m_head->_m_data;
		}

		[[nodiscard]] inline const_reference front()const noexcept
		{
			if constexpr (debug_) {
				if (empty()) {
					debug_log::derror(zuck::SEG_WrongIter,
						"Segmentfault: invalid address !");
				}
			}
			return *_m_head->_m_data;
		}

		[[nodiscard]] inline reference back()noexcept
		{
			if constexpr (debug_) {
				if (empty()) {
					debug_log::derror(zuck::SEG_WrongIter,
						"Segmentfault: invalid address !");
				}
			}
			return *_m_tail->_m_data;
		}

		[[nodiscard]] inline const_reference back()const noexcept
		{
			if constexpr (debug_) {
				if (empty()) {
					debug_log::derror(zuck::SEG_WrongIter, 
						"Segmentfault: invalid address !");
				}
			}
			return *_m_tail->_m_data;
		}

		void pop_front()
		{
			__destroy_head();
			_m_head = _m_head->_m_n;
			--_m_cnt;
		}

		void pop_back()
		{
			__destroy_tail();
			_m_tail = _m_tail->_m_p;
			--_m_cnt;
		}

		inline void push_front(const T& val) { __emplace_front(val); }

		inline void push_front(T&& val) { __emplace_front(zuck::move(val)); }

		inline void push_back(const T& val) { __emplace_back(val); }

		inline void push_back(T&& val) { __emplace_back(zuck::move(val)); }

		inline iterator insert(const_iterator _Where, T&& val)
		{
			return __emplace_aux(_Where, zuck::move(val));
		}

		inline iterator insert(const_iterator _Where, const T& val)
		{
			return __emplace_aux(_Where, val);
		}

		inline void resize(const size_type _Size, const T& val = T{})
		{ 
			__resize(_Size, val);
		}

		void reverse()
		{
			for (_Node_ptr _Begin = _m_head, _End = _m_tail;
				 _Begin != _End;
				 _Begin = _Begin->_m_n, _End = _End->_m_p)
			{
				zuck::swap(_Begin->_m_data, _End->_m_data);
			}
		}

		inline void swap(_Self& other)noexcept
		{
			if (*this != other) {
				auto _Tmp = zuck::move(*this);
				*this     = zuck::move(other);
				other     = zuck::move(_Tmp);
			}
		}

        template<typename compare = zuck::less<T>>
		void sort(const compare& _less = less<T>{})
		{
			for (_Node_ptr _Indi = _m_head; _Indi != null; _Indi = _Indi->_m_n) {
				_Node_ptr _Tmp = _Indi;
				for (_Node_ptr _Indj = _Indi->_m_n; _Indj != null; _Indj = _Indj->_m_n) {
					if (_less(_Indj->_m_data, _Tmp->_m_data)) {
						_Tmp = _Indj;
					}
				}
				if (_Tmp != _Indi) {
					zuck::swap(_Tmp->_m_data, _Indi->_m_data);
				}
			}
		}

		[[nodiscard]] inline iterator find(const T& val)const noexcept
		{
			return iterator(__get_addr(val));
		}

		[[nodiscard]] inline iterator find(T&& val)const noexcept
		{
			return iterator(__get_addr(zuck::move(val)));
		}

		[[nodiscard]] inline bool empty()const noexcept
		{ 
			return static_cast<bool>(_m_head == null || !_m_head->_m_data);
		}

		[[nodiscard]] inline size_type size()const noexcept { return _m_cnt; }

		[[nodiscard]] inline size_type max_size()const noexcept
		{
			return _Alty_tts::max_size();
		}

		[[nodiscard]] inline iterator begin()noexcept
		{ 
			return iterator(_m_head);
		}

		[[nodiscard]] inline const_iterator begin()const noexcept
		{ 
			return const_iterator(_m_head);
		}

		[[nodiscard]] inline const_iterator cbegin()const noexcept
		{ 
			return const_iterator(_m_head);
		}

		[[nodiscard]] inline iterator end()noexcept
		{
			return iterator(_m_tail->_m_n, _m_tail);
		}

		[[nodiscard]] inline const_iterator end()const noexcept
		{ 
			return const_iterator(_m_tail->_m_n, _m_tail);
		}

		[[nodiscard]] inline const_iterator cend()const noexcept
		{ 
			return const_iterator(_m_tail->_m_n, _m_tail);
		}

		[[nodiscard]] inline reverse_iterator rbegin()noexcept
		{ 
			return reverse_iterator(_m_tail);
		}

		[[nodiscard]] inline const_reverse_iterator rbegin()const noexcept
		{ 
			return const_reverse_iterator(_m_tail);
		}

		[[nodiscard]] inline const_reverse_iterator crbegin()const noexcept
		{
			return const_reverse_iterator(_m_tail);
		}

		[[nodiscard]] inline reverse_iterator rend()noexcept
		{
			return reverse_iterator(_m_head->_m_p, _m_head);
		}

		[[nodiscard]] inline const_reverse_iterator rend()const noexcept
		{
			return const_reverse_iterator(_m_head->_m_p, _m_head);
		}

		[[nodiscard]] inline const_reverse_iterator crend()const noexcept
		{ 
			return const_reverse_iterator(_m_head->_m_p, _m_head);
		}

		inline _Self& operator=(const _Self& other)
		{ 
			__construct_range(other.begin(), other.end());
			return *this;
		}

		inline _Self& operator=(_Self&& other)noexcept
		{
			__move_construct(zuck::forward<list>(other));
			return *this;
		}

		[[nodiscard]] inline bool operator==(const _Self& other)const noexcept
		{
			return static_cast<bool>((_m_cnt == other.size())
				&& __equal_with(other, zuck::equal_to<T>{}));
		}

		[[nodiscard]] inline bool operator!=(const _Self& other)const noexcept
		{
			return static_cast<bool>((_m_cnt != other.size())
				|| __not_equal_with(other, zuck::not_equal_to<T>{}));
		}

	private:
		template<typename PointerType>
		void __assign_range(PointerType first, PointerType last)
		{
			size_type const _Newsize = zuck::distance(first, last);	
			__verify_size(_Newsize);

			size_type const _Oldsize = size();
			auto _First		= begin();
			auto const _End	= end();
			_m_cnt = _Newsize;
			if (_Newsize > _Oldsize) {
				auto _Next = zuck::advance(first, _Oldsize);
				_Alty_tts::destruct_range(_First, _End);
				zuck::fill(first, last, _First, _End);
				for (auto i = _Next; i != last; ++i) {
					__emplace_back(*i);
				}
				return;
			}
			__free_tail_n(_Oldsize - _Newsize);
			zuck::fill(first, last, _First, _End);
		}

		template<typename ...Args>
		void __construct_n(size_type _Newsize, Args&&... args)
		{
			__verify_size(_Newsize);
			
			for (; _Newsize; --_Newsize) {
				__construct_aux(zuck::forward<Args>(args)...);
			}
		}

		// use to construct list except copy constructor
		template<typename Iterator,
			zuck::enable_if_t<zuck::is_iterator_v<Iterator>, int> = 0>
		void __construct_range(Iterator Begin, Iterator End)
		{
			auto const _Size = zuck::distance(Begin, End);
			__verify_size(_Size);

			_m_cnt = _Size;
			for (; Begin != End; ++Begin) {
				__construct_aux(*Begin);
			}
		}

		template<typename ...Args>
		void __construct_aux(Args&&... args)
		{
			if (!_m_head) {
				_m_head = _Node_Alloc::_Allocate(alloc.allocate(1));
				_m_tail = _m_head;
				_Alty_tts::construct(_m_head->_m_data, zuck::forward<Args>(args)...);
				return;
			}
			_m_tail->_m_n = _Node_Alloc::_Allocate(alloc.allocate(1), null, _m_tail);
			_m_tail       = _m_tail->_m_n;
			_Alty_tts::construct(_m_tail->_m_data, args);
		}

		void __free_tail_n(size_type _N)
		{
			for (; _N; --_N) {
				__destroy_tail();
				_m_tail = _m_tail->_m_p;
			}
		}

		_Node_ptr __get_addr(const T& other)const noexcept
		{
			_Node_ptr _Tmp = _m_head;
			for (; _Tmp != null; _Tmp = _Tmp->_m_n) {
				if (*(_Tmp->_m_data) == other) {
					return _Tmp;
				}
			}
			return null;
		}

		template<typename ...Args>
		void __resize(size_type _Newsize, Args&&... args)
		{
			__verify_size(_Newsize);

			auto const _Oldsize = size();
			_m_cnt = _Newsize;
			if (_Newsize > _Oldsize) {
				for (int i = 0; i < _Newsize - _Oldsize; ++i) {
					__emplace_back(zuck::forward<Args>(args)...);
				}
				return;
			}
			if (_Newsize < _Oldsize) {
				__free_tail_n(_Oldsize - _Newsize);
			}
		}

		bool __rm_node(const T& Valty)
		{
			_Node_ptr _Pos = __get_addr(Valty);
			if (!_Pos) {
				return false;
			}
			if (_Pos == _m_head) {
				_m_head       = _m_head->_m_n;
				_m_head->_m_p = _Pos->_m_p;
				alloc.deallocate(_Pos->_m_data);
				_Node_Alloc::_Deallocate(_Pos);
				return true;
			}
			else if (_Pos == _m_tail) {
				_m_tail      = _m_tail->_m_p;
				_m_tail->_m_n = _Pos->_m_n;
				alloc.deallocate(_Pos->_m_data);
				_Node_Alloc::_Deallocate(_Pos);
				return true;
			}
			else {
				_Pos->_m_p->_m_n = _Pos->_m_n;
				_Pos->_m_n->_m_p = _Pos->_m_p;
				alloc.deallocate(_Pos->_m_data);
				_Node_Alloc::_Deallocate(_Pos);
				return true;
			}
			return false;
		}

		void __destroy_list()
		{
			if (!_m_head) {
				return;
			}
			for (; _m_head->_m_p; _m_head = _m_head->_m_p);
			_m_tail = _m_head;
			for (; _m_tail;) {
				_m_head = _m_head->_m_n;
				alloc.deallocate(_m_tail->_m_data, 1);
				_Node_Alloc::_Deallocate(_m_tail);
				_m_tail = _m_head;
			}
			_m_cnt = 0;
		}

		void __destroy_data()
		{
			_Node_ptr _Tmp = _m_head;
			_Node_ptr _End = _m_tail->_m_n;
			for (; _Tmp != _End; _Tmp = _Tmp->_m_n) {
				_Alty_tts::destruct(*_Tmp->_m_data);
				alloc.deallocate(_Tmp->_m_data, sizeof(T));
			}
			_m_cnt = 0;
		}

		void __destroy_head()
		{
			_Alty_tts::destruct(*(_m_head->_m_data));
			alloc.deallocate(_m_head->_m_data, 1);
			_m_head->_m_data = null;
		}

		void __destroy_tail()
		{
			_Alty_tts::destruct(*(_m_tail->_m_data));
			alloc.deallocate(_m_tail->_m_data, 1);
			_m_tail->_m_data = null;
		}

		template<typename...Args>
		iterator __emplace_front(Args&&... args)
		{
			__verify_size(_m_cnt);
			if (!_m_head) {
				_m_head = _Node_Alloc::_Allocate(alloc.allocate(1), null, null);
				_m_tail = _m_head;
				_Alty_tts::construct(_m_head->_m_data, zuck::forward<Args>(args)...);
				++_m_cnt;
				return iterator(_m_head);
			}
			if (!_m_head->_m_p) {
				_m_head->_m_p = _Node_Alloc::_Allocate(alloc.allocate(1), _m_head);
				_m_head = _m_head->_m_p;
				_Alty_tts::construct(_m_head->_m_data, zuck::forward<Args>(args)...);
				++_m_cnt;
				return iterator(_m_head);
			}
			_m_head = _m_head->_m_p;
			_m_head->_m_data = alloc.allocate(1);
			_Alty_tts::construct(_m_head->_m_data, zuck::forward<Args>(args)...);
			++_m_cnt;
			return iterator(_m_head);
		}

		template<typename...Args>
		iterator __emplace_back(Args&&... args)
		{
			__verify_size(_m_cnt);
			if (!_m_head) {
				_m_head = _Node_Alloc::_Allocate(null, null, null);
				_m_head->_m_data = alloc.allocate(1);
				_m_tail = _m_head;
				_Alty_tts::construct(_m_tail->_m_data, zuck::forward<Args>(args)...);
				++_m_cnt;
				return iterator(_m_head);
			}
			if (!_m_tail->_m_n) {
				_m_tail->_m_n = _Node_Alloc::_Allocate(null, null, _m_tail);
				_m_tail->_m_data = alloc.allocate(1);
				_m_tail = _m_tail->_m_n;
				_Alty_tts::construct(_m_tail->_m_data, zuck::forward<Args>(args)...);
				++_m_cnt;
				return iterator(_m_tail);
			}
			_m_tail->_m_data = alloc.allocate(1);
			_Alty_tts::construct(_m_tail->_m_data, zuck::forward<Args>(args)...);
			_m_tail = _m_tail->_m_n;
			++_m_cnt;
			return iterator(_m_tail);
		}

		inline void __move_construct(_Self&& other)noexcept
		{
			__verify_list();
			_m_head = other._m_head;
			_m_tail = other._m_tail;
			_m_cnt  = other._m_cnt;
			other._m_head = null;
			other._m_tail = null;
			other._m_cnt  = 0;
		}

		template<typename...Args>
		iterator __emplace_aux(const_iterator _Where, Args&&...args)
		{			
			if (_Where == begin()) {
				return __emplace_front(zuck::forward<Args>(args)...);
			}
			if (_Where == end()) {
				return __emplace_back(zuck::forward<Args>(args)...);
			}

			__verify_size(_m_cnt);
			_Node_ptr _WhN = _Where.get_unwrapped();
			_Node_ptr _Pre = _WhN->_m_p;
			_Node_ptr _New = _Node_Alloc::_Allocate(null, _WhN, _Pre);
			_WhN->_m_p = _New;
			_Pre->_m_n = _New;
			_New->_m_data = alloc.allocate(1);
			_Alty_tts::construct(_New->_m_data, zuck::forward<Args>(args)...);
			++_m_cnt;
			return iterator(_New);
		}

		template<typename _Equal>
		bool __not_equal_with(const _Self& other, _Equal _Pr)const noexcept
		{
			_Node_ptr proxy = _m_head;
			for (auto& itm : other) {
				if (proxy->_m_data != itm) {
					return true;
				}
			}
			return false;
		}

		template<typename _Equal>
		bool __equal_with(const _Self& other, _Equal _Pr)const noexcept
		{
			_Node_ptr proxy = _m_head;
			for (auto& itm : other) {
				if (proxy->_m_data != itm) {
					return false;
				}
			}
			return true;
		}

		inline void __verify_size(const size_type _Size)
		{
			if (max_size() < _Size) {
				debug_log::derror(zuck::SEG_LengthTooLong, 
					"list length too long !");
			}
		}

		inline void __verify_list()
		{
			if (!empty()) {
				__destroy_data();
			}
		}
	};


	template<typename T, typename Alloc = zuck::allocator<T>>
	list(zuck::size_t, T)->list<T, Alloc>;

	template<typename T, typename Alloc = zuck::allocator<T>>
	list(zuck::size_t, T, Alloc)->list<T, Alloc>;

	template<typename T, typename Alloc = zuck::allocator<T>>
	list(std::initializer_list<T>)->list<T, Alloc>;

	template<typename T, typename Alloc = zuck::allocator<T>>
	list(std::initializer_list<T>i, Alloc)->list<T, Alloc>;

	template<typename T, typename Alloc = zuck::allocator<T>>
	list(const list<T, Alloc>&)->list<T>;

	template<typename T, typename Alloc = zuck::allocator<T>>
	list(list<T, Alloc>&&)->list<T, Alloc>;

	template<typename Iterator, typename T = zuck::iter_traits_t<Iterator>, 
		typename Alloc = zuck::allocator<T>>
	list(Iterator, Iterator)->list<T, Alloc>;

	template<typename T, typename Alloc = zuck::allocator<T>>
	using ZList = list<T, Alloc>;
}

